/*!
 * @file    	apm32f10x_dac.c
 * @brief	 	This file provides all the DAC firmware functions
 *
 * @details	
 *
 * @version		V1.0.0
 * @author  	
 * @date    	2019-8-6
 *
 */
#include "apm32f10x_dac.h"
#include "apm32f10x_rcm.h"

/*!
 * @brief		Reset dac peripheral registers to their default reset values
 *
 * @param		None
 *
 * @retval		None
 *
 * @note 
 */
void DAC_Reset(void)
{
	/* Enable DAC reset state */
	RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_DAC);
	/* Release DAC from reset state */
	RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_DAC);
}

/*!
 * @brief		Config the DAC peripheral according to the specified parameters in the configStruct
 *
 * @param		channel: Select the DAC channel
 *
 * @param		configStruct: pointer to a DAC_ConfigStruct_T structure
 *
 * @retval		None
 *
 * @note 
 */
void DAC_Config(uint32_t channel, DAC_ConfigStruct_T* configStruct)
{
	uint32_t tmp1 = 0, tmp2 = 0;
	/* Get the DAC CTRL value*/
	tmp1 = DAC->CTRL;
	/* Clear CTRL */
	tmp1 &= ~(((uint32_t)0x00000FFE) << channel);
	/* Set values */
	tmp2 = (configStruct->Trigger | configStruct->WaveGeneration | configStruct->LFSRUnmask_TriangleAmplitude | configStruct->OutputBuffer);
	tmp1 |= tmp2 << channel;
	/* Write to DAC CTRL */
	DAC->CTRL = tmp1;
}

/*!
 * @brief		Fills each DAC_ConfigStruct_T member with its default value
 *
 * @param		configStruct: pointer to a DAC_ConfigStruct_T structure which will be initialized
 *
 * @retval		None
 *
 * @note 
 */
void DAC_StructInit(DAC_ConfigStruct_T* configStruct)
{
	/* Initialize the DAC_Trigger member */
	configStruct->Trigger = DAC_TRIGGER_NONE;
	/* Initialize the DAC_WaveGeneration member */
	configStruct->WaveGeneration = DAC_WAVE_GENERATION_NONE;
	/* Initialize the DAC_LFSRUnmask_TriangleAmplitude member */
	configStruct->LFSRUnmask_TriangleAmplitude = DAC_LFSRU_NMASK_BIT0;
	/* Initialize the DAC_OutputBuffer member */
	configStruct->OutputBuffer = DAC_OUTPUT_BUFFER_ENBALE;
}

/*!
 * @brief		Enables the specified DAC peripheral
 *
 * @param		dac: Select the DAC or the DAC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void DAC_Enable(DAC_CHANNEL_T channel)
{
	DAC->CTRL |= 0x00000001 << channel;
}

/*!
 * @brief		Disables the specified DAC peripheral
 *
 * @param		dac: Select the DAC or the DAC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void DAC_Disable(DAC_CHANNEL_T channel)
{
	DAC->CTRL &= ~(0x00000001 << channel);
}


/*!
 * @brief		Enables the specified DAC channel DMA request
 *
 * @param		channel: Select the DAC channel
 *
 * @retval		None
 *
 * @note 
 */
void DAC_DMA_Enable(DAC_CHANNEL_T channel)
{
	DAC->CTRL |= 0x00001000 << channel;
}

/*!
 * @brief		Disables the specified DAC channel DMA request
 *
 * @param		channel: Select the DAC channel
 *
 * @retval		None
 *
 * @note 
 */
void DAC_DMA_Disable(DAC_CHANNEL_T channel)
{
	DAC->CTRL &= ~(0x00001000 << channel);
}

/*!
 * @brief		Enables the selected DAC channel software trigger
 *
 * @param		channel: Select the DAC channel
 *
 * @retval		None
 *
 * @note 
 */
void DAC_EnableSoftwareTrigger(DAC_CHANNEL_T channel)
{
    DAC->SWTRG |= (uint32_t)(0x01 << (channel >> 4));
}

/*!
 * @brief		Disable the selected DAC channel software trigger
 *
 * @param		channel: Select the DAC channel
 *
 * @retval		None
 *
 * @note 
 */
void DAC_DisableSoftwareTrigger(DAC_CHANNEL_T channel)
{
    DAC->SWTRG &= (uint32_t)~(0x01 << (channel >> 4));
}
/*!
 * @brief		Enables simultaneously the two DAC channels software
 *
 * @param		None
 *
 * @retval		None
 *
 * @note 
 */
void DAC_DualSoftwareTrigger_Enable(void)
{
	DAC->SWTRG |= 0x00000003;
}

/*!
 * @brief		Disables simultaneously the two DAC channels software
 *
 * @param		None
 *
 * @retval		None
 *
 * @note 
 */
void DAC_DualSoftwareTrigger_Disable(void)
{
    DAC->SWTRG &= 0xFFFFFFFC;
}

/*!
 * @brief		Enables the selected DAC channel wave generation
 *
 * @param		channel: Select the DAC channel
 *
 * @param		wave: Select the wave
 *
 * @retval		None
 *
 * @note 
 */
void DAC_WaveGeneration_Enable(DAC_CHANNEL_T channel, DAC_WAVE_GENERATION_T wave)
{
	DAC->CTRL |= wave << channel;
}

/*!
 * @brief		Disables the selected DAC channel wave generation
 *
 * @param		channel: Select the DAC channel
 *
 * @param		wave: Select the wave
 *
 * @retval		None
 *
 * @note 
 */
void DAC_WaveGeneration_Disable(DAC_CHANNEL_T channel, DAC_WAVE_GENERATION_T wave)
{
	DAC->CTRL &= ~(wave << channel);
}

/*!
 * @brief		Set the specified data holding register value for DAC channel1
 *
 * @param		align: DAC channel1 data alignment
 *
 * @param		data: Data to be loaded in the selected data holding register
 *
 * @retval		None
 *
 * @note 
 */
void DAC_SetChannel1Data(DAC_ALIGN_T align, uint16_t data)
{
	__IO uint32_t tmp = 0;

	tmp = (uint32_t)DAC_BASE; 
	tmp += 0x00000008 + align;

	/* Set the DAC channel1 selected data holding register */
	*(__IO uint32_t *) tmp = data;
}

/*!
 * @brief		Set the specified data holding register value for DAC channel2
 *
 * @param		align: DAC channel2 data alignment
 *
 * @param		data: Data to be loaded in the selected data holding register
 *
 * @retval		None
 *
 * @note 
 */
void DAC_SetChannel2Data(DAC_ALIGN_T align, uint16_t data)
{
	__IO uint32_t tmp = 0;

	tmp = (uint32_t)DAC_BASE; 
	tmp += 0x00000014 + align;

	/* Set the DAC channel1 selected data holding register */
	*(__IO uint32_t *) tmp = data;
}

/*!
 * @brief		Set the specified data holding register value for dual DAC channel
 *
 * @param		align: Dual DAC channel data alignment
 *
 * @param		data2: Data for channel2 to be loaded in the selected data holding register
 *
 * @param		data1: Data for channel1 to be loaded in the selected data holding register
 *
 * @retval		None
 *
 * @note 
 */
void DAC_SetDualChannelData(DAC_ALIGN_T align, uint16_t data2, uint16_t data1)
{
	uint32_t data = 0, tmp = 0;

	/* Calculate and set dual DAC data holding register value */
	if (align == DAC_ALIGN_8B_R)
	{
        data = ((uint32_t)data2 << 8) | data1; 
	}
	else
	{
        data = ((uint32_t)data2 << 16) | data1;
	}

	tmp = (uint32_t)DAC_BASE;
	tmp += 0x00000020 + align;

	/* Set the dual DAC selected data holding register */
	*(__IO uint32_t *)tmp = data;
}

/*!
 * @brief		Reads the specified DAC channel data output value
 *
 * @param		channel: Select the DAC channel
 *
 * @retval		The data output value of the specified DAC channel
 *
 * @note 
 */
uint16_t DAC_ReadDataOutputValue(DAC_CHANNEL_T channel)
{
	__IO uint32_t tmp = 0;

	tmp = (uint32_t) DAC_BASE ;
	tmp += 0x0000002C + ((uint32_t)channel >> 2);

	/* Returns the DAC channel data output register value */
	return (uint16_t) (*(__IO uint32_t*) tmp);
}
